﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Linq;

namespace TetrisClient
{
    /// <summary>
    /// This class is responsible for manipulating the Grid which is always being refreshed by the client side.
    /// </summary>
    public class GridManipulator
    {
        private Grid gameBoard;

        /// <summary>
        /// Initializes a new instance of the <see cref="GridManipulator"/> class.
        /// </summary>
        /// <param name="gameBoard">The game board.</param>
        public GridManipulator(Grid gameBoard)
        {
            this.gameBoard = gameBoard;
        }

        /// <summary>
        /// Creates the conlumns and lines of the game board.
        /// </summary>
        /// <param name="numColumns">The num columns.</param>
        /// <param name="numRows">The num rows.</param>
        public void createGameBoard(int numColumns, int numRows)
        {
            if (isBoardCreated())
            {
                cleanBoard(numColumns, numRows);
                return;
            }
            for (int column = 0; column < numColumns; column++)
            {
                ColumnDefinition columnDefinition = new ColumnDefinition();
                gameBoard.ColumnDefinitions.Add(columnDefinition);
            }
            for (int row = 0; row < numRows; row++)
            {
                RowDefinition rowDefinition = new RowDefinition();
                gameBoard.RowDefinitions.Add(rowDefinition);
            }
            for (int row = 0; row < numRows; row++)
            {
                for (int column = 0; column < numColumns; column++)
                {
                    createCell(column, row);
                }
            }
        }
        /// <summary>
        /// Determines if the board has been created.
        /// </summary>
        /// <returns>
        ///   <c>true</c> if [is board created]; otherwise, <c>false</c>.
        /// </returns>
        private bool isBoardCreated()
        {
            return gameBoard.RowDefinitions.Count > 2 || gameBoard.ColumnDefinitions.Count > 2;
        }

        /// <summary>
        /// Cleans the board.
        /// </summary>
        /// <param name="numColumns">The num columns.</param>
        /// <param name="numRows">The num rows.</param>
        private void cleanBoard(int numColumns, int numRows)
        {
            for (int row = 0; row < numRows; row++)
            {
                for (int column = 0; column < numColumns; column++)
                {
                    cleanCell(column, row);
                }
            }
        }

        /// <summary>
        /// Updates the game board according to the bidimensional array of integer..
        /// </summary>
        /// <param name="board">The board.</param>
        public void updateGameBoard(int[][] board)
        {
            for (int row = 0; row < board.Length; row++)
            {
                for (int column = 0; column < board[row].Length; column++)
                {
                    if (board[row][column] != 0)
                    {
                        fillCell(column, row, Math.Abs(board[row][column]));
                    }
                    else
                    {
                        cleanCell(column, row);
                    }
                }
            }
        }

        /// <summary>
        /// returns the color according with the number.
        /// </summary>
        /// <param name="colorNum">The color num.</param>
        /// <returns></returns>
        private SolidColorBrush color(int colorNum)
        {
            switch (colorNum)
            {
                case 1: // I
                    return new SolidColorBrush(System.Windows.Media.Colors.Red);
                case 2: // J
                    return new SolidColorBrush(System.Windows.Media.Colors.Yellow);
                case 3: // L
                    return new SolidColorBrush(System.Windows.Media.Colors.Magenta);
                case 4: // O
                    return new SolidColorBrush(System.Windows.Media.Colors.Blue);
                case 5: // S
                    return new SolidColorBrush(System.Windows.Media.Colors.Cyan);
                case 6: // T
                    return new SolidColorBrush(System.Windows.Media.Colors.Green);
                case 7: // Z
                    return new SolidColorBrush(System.Windows.Media.Colors.Orange);
                default: // BLACK
                    return new SolidColorBrush(System.Windows.Media.Colors.White);
            }
        }

        /// <summary>
        /// Creates the border and the retangle wich represents a cell on the grid.
        /// </summary>
        /// <param name="column">The column.</param>
        /// <param name="row">The row.</param>
        private void createCell(int column, int row)
        {
            Border border = new Border
            {
                Name = borderName(column, row),
                BorderThickness = new Thickness(1),
                BorderBrush = new SolidColorBrush(System.Windows.Media.Colors.Black),
                Background = new SolidColorBrush(System.Windows.Media.Colors.Black)
            };
            
            Rectangle cell = new Rectangle
            {
                Name = cellName(column, row),
                Fill = new SolidColorBrush(System.Windows.Media.Colors.DarkGray)
            };

            Grid.SetColumn(border, column);
            Grid.SetRow(border, row);
            border.Child = cell;

            gameBoard.Children.Add(border);
        }

        /// <summary>
        /// Pint the cell with the specific collor.
        /// </summary>
        /// <param name="column">The column.</param>
        /// <param name="row">The row.</param>
        /// <param name="colorNum">The color num.</param>
        private void fillCell(int column, int row, int colorNum)
        {
            Rectangle cell = findCell(column, row);
            if(cell != null) 
            {
                cell.Fill = color(colorNum);
            }
        }

        /// <summary>
        /// return the name of the cell. The name is made by the coordinates.
        /// </summary>
        /// <param name="column">The column.</param>
        /// <param name="row">The row.</param>
        /// <returns></returns>
        private string cellName(int column, int row)
        {
            return (column + "-" + gameBoard.Name  + "-" + row + gameBoard.Name);
        }

        /// <summary>
        /// Return the name of the border.
        /// </summary>
        /// <param name="column">The column.</param>
        /// <param name="row">The row.</param>
        /// <returns></returns>
        private string borderName(int column, int row)
        {
            return (column + "-border-" + gameBoard.Name + "-" + row + gameBoard.Name);
        }

        /// <summary>
        /// Clean the cell.
        /// </summary>
        /// <param name="column">The column.</param>
        /// <param name="row">The row.</param>
        private void cleanCell(int column, int row)
        {
            Rectangle cell = findCell(column, row);
            if (cell != null)
            {
                cell.Fill = new SolidColorBrush(System.Windows.Media.Colors.DarkGray);
            }
        }

        /// <summary>
        /// Find the cell.
        /// </summary>
        /// <param name="column">The column.</param>
        /// <param name="row">The row.</param>
        /// <returns></returns>
        private Rectangle findCell(int column, int row)
        {
            Border border = gameBoard.FindName(borderName(column, row)) as Border;
            return border.FindName(cellName(column, row)) as Rectangle;
        }
    }
}
